home *** CD-ROM | disk | FTP | other *** search
/ CD Actual Thematic 25: Programming / pc_actual_25.iso / Delphi / Duck Report / _SETUP.1 / dclDQuery.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1999-10-23  |  38.3 KB  |  1,523 lines

  1. Unit dclDQuery;
  2. {$I DQuery.inc}
  3.  
  4. Interface
  5. Uses
  6.     Windows, Messages, SysUtils, Classes, Controls, Forms, Dialogs,
  7.   DB, DBTables, DSGNINTF;
  8. Const
  9.   DQ_THIS_VERSION        = '010';
  10.     DQ_PTHIS_VERSION        = '01.0';
  11.     DQ_Display_VERSION    = '1.0c';
  12.   
  13.   TEXT_TAB                = Char(#09);
  14.   MAX_ALIAS            = 50;
  15.   MAX_PATH                = 255;
  16. Type
  17.     TDuckQuery        = Class;
  18.   PRDQTable         = ^RDQTable;
  19.     RDQTable         = Packed Record
  20.      DataBase:        String[MAX_PATH];
  21.      Table:            String[MAX_ALIAS];
  22.      Alias:            String[MAX_ALIAS];
  23.     End;
  24.     TDQLinkType        = (tltEqual, tltGreater, tltLess, tltGreaterEqual,
  25.                           tltLessEqual, tltNotEqual, tltLeftOuter,
  26.                     tltRightOuter);
  27.   PRDQLink         = ^RDQLink;
  28.     RDQLink             = Packed Record
  29.      TableLinkType:        TDQLinkType;
  30.         MAlias:                String[MAX_ALIAS];
  31.         MField:                String[MAX_ALIAS];
  32.         DAlias:                String[MAX_ALIAS];
  33.      DField:                String[MAX_ALIAS];
  34.     End;
  35.     PRDQField         = ^RDQField;
  36.     RDQField         = Packed Record
  37.      Data:            String[MAX_PATH];
  38.         ColumnName:    String[MAX_ALIAS];
  39.     End;
  40.  
  41.     TDQCriteriaAdd        = (caAnd, caor);
  42.     TDQCriteriaType    = (scNone, scEqual, scNotEqual, scLess, scLessEqual,
  43.                           scGreater, scGreaterEqual, scBetween, scBetweenEqual,
  44.                     scNOTNULL, scNULL, scIN, scLike, scNotLike);
  45.  
  46.     PRDQCriterias         = ^RDQCriterias;
  47.     RDQCriterias         = Packed Record
  48.      Field:            String[MAX_ALIAS];
  49.         CriteriaType:    TDQCriteriaType;
  50.      Value1:            String[MAX_PATH];
  51.      Value2:            String[MAX_PATH];
  52.      AddType:            TDQCriteriaAdd;
  53.     End;
  54.  
  55.   PRDQGroup         = ^RDQGroup;
  56.     RDQGroup         = Packed Record
  57.       Field:        String[MAX_ALIAS];
  58.     End;
  59.  
  60.   TDQSortType    = (gsAscending, gsDecending); { ASC, DESC }
  61.   PRDQSort            = ^RDQSort;
  62.     RDQSort             = Packed Record
  63.       SortType:    TDQSortType;
  64.         Field:        String[MAX_ALIAS];
  65.     End;
  66.  
  67.   PRDQTableInfo    = ^RDQTableInfo;
  68.     RDQTableInfo     = Packed Record
  69.       Alias:        String[MAX_ALIAS];
  70.         Table:        TTable;
  71.      FieldName:    TStrings;
  72.     End;
  73.  
  74.   TDREventFind    = Procedure (Sender: TObject;
  75.                               St: String; Var iResult: Integer) of Object;
  76.   TDREventFindPt    = Procedure (Sender: TObject;
  77.                               St: String; Var pt: Pointer) of Object;
  78.   { ---------- TDQList ---------- }
  79.     TDQList        = Class (TPersistent)
  80.   Private
  81.   Protected
  82.       FOwner:        TDuckQuery;
  83.      FSize:        Integer;
  84.      List:            TList;
  85.      FOnFind:        TDREventFind;
  86.      FOnFindPt:    TDREventFindPt;
  87.  
  88.      Function        GetCount: Integer;
  89.      Function        GetItems (Index: Integer): Pointer; Virtual;
  90.      Procedure    SetItems (Index: Integer; Item: Pointer); Virtual;
  91.      Procedure    ReadData (Stream: TStream);
  92.         Procedure    WriteData (Stream: TStream);
  93.      Procedure    DefineProperties (Filer: TFiler); Override;
  94.     Public
  95.       Constructor    Create (AOwner: TDuckQuery; ASize: Integer); Virtual;
  96.         Destructor    Destroy; Override;
  97.      Procedure    Clear;
  98.      Procedure    Assign (Source: TPersistent); Override;
  99.      Procedure    Move(CurIndex, NewIndex: Integer);
  100.      Function        Add(Item: Pointer): Integer;
  101.      Procedure    Insert (Index: Integer; Item: Pointer);
  102.      Procedure    Delete (Index: Integer);
  103.      Function        FindAsString (St: String): Integer;
  104.      Function        FindAsStringPt (St: String): Pointer;
  105.      Property        Items[Index: Integer]:    Pointer Read GetItems
  106.                                          Write SetItems; default;
  107.     Published
  108.       Property        Count:    Integer Read GetCount;
  109.      Property        Size:        Integer Read FSize;
  110.      Property        OnFind:        TDREventFind Read FOnFind Write FOnFind;
  111.      Property        OnFindPt:    TDREventFindPt Read FOnFindPt Write FOnFindPt;
  112.     End;
  113.     { ---------- TDuckQuery ---------- }
  114.     TDuckQuery = Class (TQuery)
  115.     Private
  116.   Protected
  117.       FVersion:        Integer;
  118.      FTables:            TDQList;
  119.      FTableLink:        TDQList;
  120.      FSelectFields:    TDQList;
  121.      FCriterias:        TDQList;
  122.      FGroups:            TDQList;
  123.      FSorts:            TDQList;
  124.      FTableInfo:        TDQList;
  125.      FDuplicate:        Boolean;
  126.  
  127.      Procedure        SetTables (Const Value: TDQList);
  128.         Procedure        SetTableLink (Const Value: TDQList);
  129.         Procedure        SetSelectFields (Const Value: TDQList);
  130.      Procedure        SetCriterias (Const Value: TDQList);
  131.      Procedure        SetGroups (Const Value: TDQList);
  132.      Procedure        SetSorts (Const Value: TDQList);
  133.  
  134.      Procedure        FindTable (Sender: TObject; St: String; Var iResult: Integer);
  135.      Procedure        FindTabbleInfo (Sender: TObject; St: String; Var iResult: Integer);
  136.      Procedure        FindField (Sender: TObject; St: String; Var iResult: Integer);
  137.      Procedure        FindGroup (Sender: TObject; St: String; Var iResult: Integer);
  138.      Procedure        FindSort (Sender: TObject; St: String; Var iResult: Integer);
  139.      Procedure        FindCriterias (Sender: TObject; St: String; Var iResult: Integer);
  140.  
  141.      Procedure        FindTablePt (Sender: TObject; St: String; Var pt: Pointer);
  142.      Procedure        FindTabbleInfoPt (Sender: TObject; St: String; Var pt: Pointer);
  143.      Procedure        FindFieldPt (Sender: TObject; St: String; Var pt: Pointer);
  144.  
  145.     Public
  146.       Constructor    Create (AOwner: TComponent); Override;
  147.         Destructor    Destroy; Override;
  148.      Procedure    Assign (Source: TPersistent); Override;
  149.      Procedure    GetSQL (SQL: TStrings);
  150.      Procedure    DoSQL;
  151.      Function        SaveFile (StFile: String): Boolean;
  152.      Function        OpenFile (StFile: String): Boolean;
  153.      Function        SaveTextFile (StFile: String): Boolean;
  154.      Procedure    SaveToStream (Stream: TStream);
  155.      Function        LoadFromStream (Stream: TStream): Boolean;
  156.  
  157.      Function        OpenFileDlg: Boolean;
  158.      Function        SaveFileDlg: Boolean;
  159.      Function        SaveTxtFileDlg: Boolean;
  160.      Procedure    ViewSQL;
  161.  
  162.      Procedure    Clear;
  163.      Procedure    Editor (Index: Integer);
  164.  
  165.      Property        TableInfo:    TDQList Read FTableInfo;
  166.     Published
  167.         Property        DQTables:        TDQList Read FTables Write SetTables;
  168.         Property        DQTableLinks:    TDQList Read FTableLink Write SetTableLink;
  169.         Property        DQFields:        TDQList Read FSelectFields Write SetSelectFields;
  170.      Property        DQCriterias:    TDQList Read FCriterias Write SetCriterias;
  171.      Property        DQGroups:        TDQList Read FGroups Write SetGroups;
  172.      Property        DQSorts:            TDQList Read FSorts Write SetSorts;
  173.      Property        Duplicate:        Boolean Read FDuplicate Write FDuplicate Default TRUE;
  174.     End;
  175.   { ---------- TDQListProperty ---------- }
  176.   TDQListProperty = Class(TClassProperty)
  177.     Public
  178.       Procedure    EditItem (Index: Integer);
  179.         Function        GetAttributes: TPropertyAttributes; Override;
  180.     End;
  181.   { ---------- TDQTablesProperty ---------- }
  182.   TDQTablesProperty = Class(TDQListProperty)
  183.     Public
  184.         Procedure    Edit; Override;
  185.     End;
  186.   { ---------- TDQTableLinksProperty ---------- }
  187.   TDQTableLinksProperty = Class(TDQListProperty)
  188.     Public
  189.         Procedure    Edit; Override;
  190.     End;
  191.   { ---------- TDQFieldsProperty ---------- }
  192.   TDQFieldsProperty = Class(TDQListProperty)
  193.     Public
  194.         Procedure    Edit; Override;
  195.     End;
  196.   { ---------- TDQCriteriasProperty ---------- }
  197.   TDQCriteriasProperty = Class(TDQListProperty)
  198.     Public
  199.         Procedure    Edit; Override;
  200.     End;
  201.   { ---------- TDQGroupsProperty ---------- }
  202.   TDQGroupsProperty = Class(TDQListProperty)
  203.     Public
  204.         Procedure    Edit; Override;
  205.     End;
  206.   { ---------- TDQSortsProperty ---------- }
  207.   TDQSortsProperty = Class (TDQListProperty)
  208.     Public
  209.         Procedure    Edit; Override;
  210.     End;
  211.  
  212.   { ---------- TDQListDefault ---------- }
  213.   TDQListDefault = class(TDefaultEditor)
  214.     Protected
  215.         Procedure    EditProperty(PropertyEditor: TPropertyEditor;
  216.                         var Continue, FreeEditor: Boolean); Override;
  217.   Public
  218.         Procedure    ExecuteVerb(Index: Integer); Override;
  219.         Function        GetVerb(Index: Integer): String; Override;
  220.         Function        GetVerbCount: Integer; Override;
  221.     End;
  222.  
  223. Procedure    Register;
  224. Function    DQCutCharInString (St: String; StD: String): String;
  225. Implementation
  226. Uses QueryEditor, DQViewText, DQViewData;
  227. {$R dclDQuery.Dcr}
  228. Procedure    Register;
  229. Begin
  230.     RegisterComponents ('DuckTech', [TDuckQuery]);
  231.   RegisterComponentEditor (TDuckQuery, TDQListDefault);
  232.   RegisterPropertyEditor (TypeInfo(TDQList), TDuckQuery, 'DQTables',
  233.         TDQTablesProperty);
  234.   RegisterPropertyEditor (TypeInfo(TDQList), TDuckQuery, 'DQTableLinks',
  235.         TDQTableLinksProperty);
  236.   RegisterPropertyEditor (TypeInfo(TDQList), TDuckQuery, 'DQFields',
  237.         TDQFieldsProperty);
  238.   RegisterPropertyEditor (TypeInfo(TDQList), TDuckQuery, 'DQCriterias',
  239.         TDQCriteriasProperty);
  240.   RegisterPropertyEditor (TypeInfo(TDQList), TDuckQuery, 'DQGroups',
  241.         TDQGroupsProperty);
  242.   RegisterPropertyEditor (TypeInfo(TDQList), TDuckQuery, 'DQSorts',
  243.         TDQSortsProperty);
  244. End;
  245. Function    DQCutCharInString (St: String; StD: String): String;
  246. Var
  247.     i:            Integer;
  248.   iLength:    Integer;
  249.   iFind:    Integer;
  250. Begin
  251.     Result    := St;
  252.   i            := 1;
  253.   iLength    := Length (Result);
  254.   While i <= iLength Do
  255.   Begin
  256.       iFind    := Pos (Result[i], StD);
  257.       if iFind > 0 Then
  258.      Begin
  259.          Delete (Result, i, 1);
  260.         Dec (iLength);
  261.       End
  262.      Else
  263.          Inc (i);
  264.   End;
  265. End;
  266. Function    DQGetVersion (St: String): Integer;
  267. Begin
  268.     St            := DQCutCharInString (St, '.');
  269.   Result    := StrToInt (St);
  270. End;
  271. { ---------- TDQListProperty ---------- }
  272. Procedure TDQListProperty.EditItem (Index: Integer);
  273. Var
  274.     DuckQuery:    TDuckQuery;
  275. Begin
  276.   if not (GetComponent(0) is TDuckQuery) Then Exit;
  277.     DuckQuery        := TDuckQuery (GetComponent(0));
  278.   DuckQuery.Editor (Index);
  279. End;
  280. Function TDQListProperty.GetAttributes : TPropertyAttributes;
  281. Begin
  282.   Result := [paDialog];
  283. End;
  284. { ---------- TDQTablesProperty ---------- }
  285. Procedure TDQTablesProperty.Edit;
  286. Begin
  287.     EditItem (0);
  288. End;
  289. { ---------- TDQTableLinksProperty ---------- }
  290. Procedure TDQTableLinksProperty.Edit;
  291. Begin
  292.     EditItem (1);
  293. End;
  294. { ---------- TDQFieldsProperty ---------- }
  295. Procedure TDQFieldsProperty.Edit;
  296. Begin
  297.     EditItem (2);
  298. End;
  299. { ---------- TDQCriteriasProperty ---------- }
  300. Procedure TDQCriteriasProperty.Edit;
  301. Begin
  302.     EditItem (3);
  303. End;
  304. { ---------- TDQGroupsProperty ---------- }
  305. Procedure TDQGroupsProperty.Edit;
  306. Begin
  307.     EditItem (4);
  308. End;
  309. { ---------- TDQSortsProperty ---------- }
  310. Procedure TDQSortsProperty.Edit;
  311. Begin
  312.     EditItem (5);
  313. End;
  314. { ---------- TDQListDefault ---------- }
  315. Procedure TDQListDefault.EditProperty(PropertyEditor: TPropertyEditor;
  316.   var Continue, FreeEditor: Boolean);
  317. var
  318.   PropName: string;
  319. Begin
  320.     PropName := PropertyEditor.GetName;
  321.     if (CompareText(PropName, 'DQTABLES') = 0) then
  322.   begin
  323.     PropertyEditor.Edit;
  324.     Continue := False;
  325.   end;
  326. End;
  327. Function TDQListDefault.GetVerbCount: Integer;
  328. Begin
  329.   Result := 7;
  330. End;
  331.  
  332. function TDQListDefault.GetVerb(Index: Integer): string;
  333. Begin
  334.     Case Index of
  335.       0:    Result    := 'Duck Query 1.0';
  336.      1:    Result    := 'Duck &Query Editor';
  337.      2:    Result    := '&View SQL';
  338.      3:    Result    := '&Open';
  339.      4:    Result    := '&Save';
  340.         5:    Result    := 'Save To &TextFile';
  341.      6:    Result    := '&Clear All';
  342.   Else
  343.       Result := '';
  344.   End
  345. End;
  346.  
  347. Procedure TDQListDefault.ExecuteVerb(Index: Integer);
  348. Var
  349.     DuckQuery:    TDuckQuery;
  350. Begin
  351.     if Index = 0 Then
  352.       Exit
  353.   Else
  354.     if Index = 1 Then
  355.       Edit
  356.   Else
  357.   Begin
  358.       if not (Component is TDuckQuery) Then Exit;
  359.         DuckQuery        := TDuckQuery (Component);
  360.       Case Index of
  361.          2:    // View SQL
  362.             DuckQuery.ViewSQL;
  363.             3:    // Open
  364.             DuckQuery.OpenFileDlg;
  365.          4:    // Save
  366.             DuckQuery.SaveFileDlg;
  367.             5:    // Save To &TextFile
  368.             DuckQuery.SaveTxtFileDlg;
  369.          6:    // Clear All
  370.         Begin
  371.             DuckQuery.Clear;
  372.             End;
  373.       End;
  374.   End;
  375. End;
  376. { ---------- TDQList ---------- }
  377. Constructor TDQList.Create (AOwner: TDuckQuery; ASize: Integer);
  378. Begin
  379.     inherited Create;
  380.   FOwner    := AOwner;
  381.   FSize        := ASize;
  382.   List        := TList.Create;
  383. End;
  384. Destructor TDQList.Destroy;
  385. Begin
  386.     Clear;
  387.   List.Free;
  388.     inherited Destroy;
  389. End;
  390. Function TDQList.GetCount: Integer;
  391. Begin
  392.     Result    := List.Count;
  393. End;
  394. Procedure TDQList.Clear;
  395. Var
  396.     i:        Integer;
  397.   pt:    Pointer;
  398. Begin
  399.     For i := 0 To List.Count - 1 Do
  400.   Begin
  401.       pt    := List[i];
  402.      FreeMem (pt, Size);
  403.   End;
  404.   List.Clear;
  405. End;
  406. Procedure TDQList.Assign (Source: TPersistent);
  407. Var
  408.     i:            Integer;
  409.   pt:        Pointer;
  410.   S:            TDQList;
  411. Begin
  412.     if not (Source is TDQList) Then Exit;
  413. //  inherited Assign (Source);
  414.   S    := TDQList (Source);
  415.   Clear;
  416.   FSize    := S.Size;
  417.     For i := 0 To S.List.Count - 1 Do
  418.     Begin
  419.         pt    := S.List[i];
  420.      Add (pt);
  421.     End;
  422. End;
  423. Procedure TDQList.Move (CurIndex, NewIndex: Integer);
  424. Begin
  425.     List.Move(CurIndex, NewIndex);
  426. End;
  427. Function TDQList.GetItems (Index: Integer): Pointer;
  428. Begin
  429.     Result    := nil;
  430.     if (Index < 0) or (Index >= List.Count) Then Exit;
  431.     Result    := List[Index];
  432. End;
  433. Procedure TDQList.SetItems (Index: Integer; Item: Pointer);
  434. Var
  435.     pt:    Pointer;
  436. Begin
  437.     if (Index < 0) or (Index >= List.Count) Then Exit;
  438.     pt    := List[Index];
  439.     System.Move (Item^, pt^, Size);
  440. End;
  441. Function TDQList.Add(Item: Pointer): Integer;
  442. Var
  443.     pt:    Pointer;
  444. Begin
  445.     GetMem (pt, Size);
  446.   System.Move (Item^, pt^, Size);
  447.   Result    := List.Add (pt);
  448. End;
  449. Procedure TDQList.Insert (Index: Integer; Item: Pointer);
  450. Var
  451.     pt:    Pointer;
  452. Begin
  453.     GetMem (pt, Size);
  454.   System.Move (Item^, pt^, Size);
  455.     List.Insert (Index, pt);
  456. End;
  457. Procedure TDQList.Delete (Index: Integer);
  458. Var
  459.     pt:    Pointer;
  460. Begin
  461.     if (Index < 0) or (Index >= List.Count) Then Exit;
  462.     pt    := List[Index];
  463.     FreeMem (pt, Size);
  464.     List.Delete (Index);
  465. End;
  466. {
  467. Procedure TDQList.ReadData (Reader: TReader);
  468. Var
  469.     pt:        Pointer;
  470.   i:            Integer;
  471.   iCount:    Integer;
  472. Begin
  473.   Reader.ReadListBegin;
  474.   Writer.WriteInteger (FSize);
  475.   Writer.WriteInteger (Count);
  476.   GetMem (pt, Size);
  477.   Try
  478.         Clear;
  479.         While not Reader.EndOfList Do
  480.         Begin
  481.             Reader.Read (pt^, Size);
  482.             Add (pt);
  483.         End;
  484.   Finally
  485.         FreeMem (pt, Size);
  486.     End;
  487.   Reader.ReadListEnd;
  488. End;
  489. }
  490. Procedure TDQList.ReadData (Stream: TStream);
  491. Var
  492.     pt:        Pointer;
  493.   i:            Integer;
  494.   iCount:    Integer;
  495. Begin
  496.     Clear;
  497.   Stream.ReadBuffer (FSize, Sizeof (FSize));
  498.   Stream.ReadBuffer (iCount, Sizeof (iCount));
  499.   GetMem (pt, Size);
  500.   Try
  501.         For i := 0 To iCount - 1 Do
  502.      Begin
  503.          Stream.ReadBuffer (pt^, Size);
  504.             Add (pt);
  505.         End;
  506.   Finally
  507.         FreeMem (pt, Size);
  508.     End;
  509. End;
  510. Procedure TDQList.WriteData (Stream: TStream);
  511. Var
  512.     i:        Integer;
  513. Begin
  514.     Stream.WriteBuffer (FSize, Sizeof (FSize));
  515.   i    := Count;
  516.   Stream.WriteBuffer (i, Sizeof (i));
  517.     for i := 0 to List.Count - 1 Do
  518.         Stream.WriteBuffer (List[i]^, Size);
  519. End;
  520. Procedure TDQList.DefineProperties (Filer: TFiler);
  521.     Function DoWrite: Boolean;
  522.   Begin
  523.         if Filer.Ancestor <> nil Then
  524.         Begin
  525.             Result := True;
  526.             if Filer.Ancestor is TDQList then
  527.                 Result := TRUE;
  528.         End
  529.         Else
  530.             Result := Count > 0;;
  531.     End;
  532. Begin
  533.     Filer.DefineBinaryProperty('Data', ReadData, WriteData, DoWrite);
  534. End;
  535. Function TDQList.FindAsString (St: String): Integer;
  536. Begin
  537.     Result    := -1;
  538.   if Assigned (FOnFind) Then
  539.       FOnFind (Self, St, Result);
  540. End;
  541. Function TDQList.FindAsStringPt (St: String): Pointer;
  542. Begin
  543.     Result    := nil;
  544.   if Assigned (FOnFindPt) Then
  545.       FOnFindPt (Self, St, Result);
  546. End;
  547. { ---------- TDuckQuery ---------- }
  548. Constructor TDuckQuery.Create (AOwner: TComponent);
  549. Begin
  550.     inherited Create (AOwner);
  551.   FVersion            := StrToInt (DQ_THIS_VERSION);
  552.   FDuplicate        := TRUE;
  553.     FTables            := TDQList.Create (Self, Sizeof (RDQTable));
  554.     FTableLink        := TDQList.Create (Self, Sizeof (RDQLink));
  555.     FSelectFields    := TDQList.Create (Self, Sizeof (RDQField));
  556.  
  557.   FCriterias    := TDQList.Create (Self, Sizeof (RDQCriterias));
  558.     FGroups        := TDQList.Create (Self, Sizeof (RDQGroup));
  559.     FSorts        := TDQList.Create (Self, Sizeof (RDQSort));
  560.   FTableInfo    := TDQList.Create (Self, Sizeof (RDQTableInfo));
  561.  
  562.   FTables.OnFind                := FindTable;
  563.     FTableInfo.OnFind            := FindTabbleInfo;
  564.   FSelectFields.OnFind        := FindField;
  565.   FGroups.OnFind                := FindGroup;
  566.     FSorts.OnFind                := FindSort;
  567.     FCriterias.OnFind            := FindCriterias;
  568.  
  569.   FTables.OnFindPt            := FindTablePt;
  570.     FTableInfo.OnFindPt        := FindTabbleInfoPt;
  571.   FSelectFields.OnFindPt    := FindFieldPt;
  572. End;
  573. Destructor TDuckQuery.Destroy;
  574. Begin
  575.     Clear;
  576.     FTables.Free;
  577.     FTableLink.Free;
  578.     FSelectFields.Free;
  579.   FCriterias.Free;
  580.     FGroups.Free;
  581.     FSorts.Free;
  582.   FTableInfo.Free;
  583.     inherited Destroy;
  584. End;
  585. Procedure TDuckQuery.Assign (Source: TPersistent);
  586. Var
  587.     S:    TDuckQuery;
  588. Begin
  589.     if not (Source is TDuckQuery) Then Exit;
  590. //  inherited Assign (Source);
  591.     S                    := TDuckQuery (Source);
  592.   Duplicate        := S.Duplicate;
  593.     DQTables            := S.DQTables;
  594.     DQTableLinks    := S.DQTableLinks;
  595.     DQFields            := S.DQFields;
  596.   DQCriterias        := S.DQCriterias;
  597.     DQGroups            := S.DQGroups;
  598.     DQSorts            := S.DQSorts;
  599. End;
  600. Procedure TDuckQuery.Clear;
  601. Begin
  602.     DQTables.Clear;
  603.     DQTableLinks.Clear;
  604.     DQFields.Clear;
  605.   DQCriterias.Clear;
  606.     DQGroups.Clear;
  607.     DQSorts.Clear;
  608. End;
  609. Procedure TDuckQuery.SetTables (Const Value: TDQList);
  610. Begin
  611.     FTables.Assign (Value);
  612. End;
  613. Procedure TDuckQuery.SetTableLink (Const Value: TDQList);
  614. Begin
  615.     FTableLink.Assign (Value);
  616. End;
  617. Procedure TDuckQuery.SetSelectFields (Const Value: TDQList);
  618. Begin
  619.     FSelectFields.Assign (Value);
  620. End;
  621. Procedure TDuckQuery.SetCriterias (Const Value: TDQList);
  622. Begin
  623.     FCriterias.Assign (Value);
  624. End;
  625. Procedure TDuckQuery.SetGroups (Const Value: TDQList);
  626. Begin
  627.     FGroups.Assign (Value);
  628. End;
  629. Procedure TDuckQuery.SetSorts (Const Value: TDQList);
  630. Begin
  631.     FSorts.Assign (Value);
  632. End;
  633. Procedure TDuckQuery.FindTable (Sender: TObject; St: String; Var iResult: Integer);
  634. Var
  635.     TablePtr:    PRDQTable;
  636.   i:                Integer;
  637. Begin
  638.     iResult    := -1;
  639.   For i := 0 To FTables.Count - 1 Do
  640.   Begin
  641.       TablePtr    := FTables[i];
  642.      if TablePtr.Alias = St Then
  643.      Begin
  644.          iResult    := i;
  645.         Break;
  646.      End;
  647.   End;
  648. End;
  649. Procedure TDuckQuery.FindTabbleInfo (Sender: TObject; St: String; Var iResult: Integer);
  650. Var
  651.     TableInfoPtr:    PRDQTableInfo;
  652.   i:                Integer;
  653. Begin
  654.     iResult    := -1;
  655.   For i := 0 To FTableInfo.Count - 1 Do
  656.   Begin
  657.       TableInfoPtr    := FTableInfo[i];
  658.      if TableInfoPtr.Alias = St Then
  659.      Begin
  660.          iResult    := i;
  661.         Break;
  662.      End;
  663.   End;
  664. End;
  665. Procedure TDuckQuery.FindField (Sender: TObject; St: String; Var iResult: Integer);
  666. Var
  667.     FieldPtr:    PRDQField;
  668.   i:                Integer;
  669. Begin
  670.     iResult    := -1;
  671.   For i := 0 To FSelectFields.Count - 1 Do
  672.   Begin
  673.       FieldPtr    := FSelectFields[i];
  674.      if FieldPtr.ColumnName = St Then
  675.      Begin
  676.          iResult    := i;
  677.         Break;
  678.      End;
  679.   End;
  680. End;
  681. Procedure TDuckQuery.FindGroup (Sender: TObject; St: String; Var iResult: Integer);
  682. Var
  683.     GroupPtr:    PRDQGroup;
  684.   i:                Integer;
  685. Begin
  686.     iResult    := -1;
  687.   For i := 0 To FGroups.Count - 1 Do
  688.   Begin
  689.       GroupPtr    := FGroups[i];
  690.      if GroupPtr.Field = St Then
  691.      Begin
  692.          iResult    := i;
  693.         Break;
  694.      End;
  695.   End;
  696. End;
  697. Procedure TDuckQuery.FindSort (Sender: TObject; St: String; Var iResult: Integer);
  698. Var
  699.     SortPtr:        PRDQSort;
  700.   i:                Integer;
  701. Begin
  702.     iResult    := -1;
  703.   For i := 0 To FSorts.Count - 1 Do
  704.   Begin
  705.       SortPtr    := FSorts[i];
  706.      if SortPtr.Field = St Then
  707.      Begin
  708.          iResult    := i;
  709.         Break;
  710.      End;
  711.   End;
  712. End;
  713. Procedure TDuckQuery.FindCriterias (Sender: TObject; St: String; Var iResult: Integer);
  714. Var
  715.     CriteriasPtr:    PRDQCriterias;
  716.   i:                    Integer;
  717. Begin
  718.     iResult    := -1;
  719.   For i := 0 To FCriterias.Count - 1 Do
  720.   Begin
  721.         CriteriasPtr    := FCriterias[i];
  722.      if CriteriasPtr.Field = St Then
  723.      Begin
  724.          iResult    := i;
  725.         Break;
  726.      End;
  727.   End;
  728. End;
  729.  
  730. Procedure TDuckQuery.FindTablePt (Sender: TObject; St: String; Var pt: Pointer);
  731. Var
  732.     i:        Integer;
  733. Begin
  734.     pt        := nil;
  735.     FindTable (Sender, St, i);
  736.   if i >= 0 Then
  737.       pt    := FTables[i];
  738. End;
  739. Procedure TDuckQuery.FindTabbleInfoPt (Sender: TObject; St: String; Var pt: Pointer);
  740. Var
  741.     i:        Integer;
  742. Begin
  743.     pt   := nil;
  744.     FindTabbleInfo (Sender, St, i);
  745.   if i >= 0 Then
  746.       pt    := FTableInfo[i];
  747. End;
  748. Procedure TDuckQuery.FindFieldPt (Sender: TObject; St: String; Var pt: Pointer);
  749. Var
  750.     i:        Integer;
  751. Begin
  752.     pt   := nil;
  753.     FindField (Sender, St, i);
  754.   if i >= 0 Then
  755.       pt    := DQFields[i];
  756. End;
  757. Procedure TDuckQuery.DoSQL;
  758. Begin
  759.     GetSQL (SQL);
  760. End;
  761. Procedure TDuckQuery.GetSQL (SQL: TStrings);
  762. Label
  763.     ExieSQL;
  764. Var
  765.     i:                    Integer;
  766.   iTemp:            Integer;
  767.   bOuter:            Boolean;
  768.   bWhere:            Boolean;
  769.   bSameReport:    Boolean;
  770.  
  771.   TablePtr:        PRDQTable;
  772.   TableOuterPtr:    PRDQTable;
  773.     LinkPtr:            PRDQLink;
  774.   LinkOPtr:        PRDQLink;
  775.   FieldPtr:        PRDQField;
  776.   GroupPtr:        PRDQGroup;
  777.   SortPtr:            PRDQSort;
  778.   CriteriasPtr:    PRDQCriterias;
  779.   TableInfoPtr:    PRDQTableInfo;
  780.  
  781.   StSQL:            String;
  782.  
  783.   {$IFDEF VERIFY_MSACCESS}
  784.   bAccess:            Boolean;
  785.   StDB:                String;
  786.     {$ENDIF}
  787.  
  788.   Function        FindOuter (bTarget: Boolean): Boolean;
  789.   Var
  790.       j:                    Integer;
  791.      St:                String;
  792.   Begin
  793.       Result    := FALSE;
  794.      For j := 0 To FTableLink.Count - 1 Do
  795.       Begin
  796.           LinkOPtr    := FTableLink[j];
  797.         Case LinkOPtr.TableLinkType of
  798.            tltLeftOuter,
  799.            tltRightOuter:
  800.            Begin
  801.                     if bTarget Then    St    := LinkOPtr.DAlias
  802.               Else                    St    := LinkOPtr.MAlias;
  803.                if St = TablePtr.Alias Then
  804.               Begin
  805.                   Result    := TRUE;
  806.                  Break;
  807.               End;
  808.            End;
  809.         End;
  810.      End;
  811.      if not Result Then
  812.          LinkOPtr    := nil;
  813.   End;
  814.   Procedure    PutTable (ATablePtr: PRDQTable);
  815.   Begin
  816.       if ATablePtr.DataBase = '' Then
  817.      Begin
  818. {         bSameReport    := TRUE;
  819.         StSQL    := '''';
  820.             StSQL    := StSQL + FDirectory;
  821.         StSQL    := StSQL + '\';
  822.         StSQL    := StSQL + DRTable.Table;
  823.         StSQL    := StSQL + '''';}
  824.      End
  825.      Else
  826.             if ATablePtr.DataBase[Length (ATablePtr.DataBase)] = '\' Then
  827.          Begin
  828.              StSQL    := StSQL + '''';
  829.            StSQL    := StSQL + ATablePtr.DataBase;
  830.              StSQL    := StSQL + ATablePtr.Table;
  831.            StSQL    := StSQL + '''';
  832.          End
  833.          Else
  834.          Begin
  835.            {$IFDEF VERIFY_MSACCESS}
  836.            if bAccess Then
  837.               StSQL    := StSQL + '[' + ATablePtr.Table + ']'
  838.            Else
  839.            Begin
  840.            {$ENDIF}
  841.                StSQL    := StSQL + ''':';
  842.                StSQL    := StSQL + ATablePtr.DataBase;
  843.                  StSQL    := StSQL + ':';
  844.                StSQL    := StSQL + ATablePtr.Table;
  845.                StSQL    := StSQL + '''';
  846.            {$IFDEF VERIFY_MSACCESS}
  847.            End;
  848.            {$ENDIF}
  849.          End;
  850.         StSQL    := StSQL + ' ';
  851.      StSQL    := StSQL + ATablePtr.Alias;
  852.   End;
  853.  
  854.   {$IFDEF VERIFY_MSACCESS}
  855.   Procedure    StrCatStrNotString (St: String);
  856.   Var
  857.       iPos:    Integer;
  858.   Begin
  859.       iPos    := Pos ('''', St);
  860.      if iPos <= 0 Then Exit;
  861.      St[iPos]    := '[';
  862.  
  863.         iPos    := Pos ('''', St);
  864.      if iPos <= 0 Then Exit;
  865.      St[iPos]    := ']';
  866.      StSQL    := StSQL + St;
  867.   End;
  868.   Function    TestAccess: String;
  869.   Var
  870.       i:                    Integer;
  871.      TempSession:    TSession;
  872.      St:                String;
  873.   Begin
  874.       Result    := '';
  875.      TempSession    := DBSession;
  876.      if TempSession = nil Then
  877.          TempSession    := Session;
  878.      For i := 0 To FTables.Count - 1 Do
  879.       Begin
  880.           TablePtr    := FTables[i];
  881.             if TablePtr = nil Then Continue;
  882.         St    := TempSession.GetAliasDriverName (TablePtr.DataBase);
  883.         if St = 'MSACCESS' Then
  884.         Begin
  885.            Result    := TablePtr.DataBase;
  886.            Exit;
  887.         End;
  888.         End;
  889.   End;
  890.   {$ENDIF}
  891. Begin
  892.     {$IFDEF VERIFY_MSACCESS}
  893.     bAccess    := FALSE;
  894.   StDB        := '';
  895.   {$ENDIF}
  896.   
  897.   SQL.Clear;
  898.   SQL.BeginUpdate;
  899.   Try
  900.     StSQL    := 'SELECT';
  901.   if FDuplicate Then
  902.         StSQL    := StSQL + ' DISTINCT';
  903.   {$IFDEF VERIFY_MSACCESS}
  904.     StDB        := TestAccess;
  905.   if StDB <> '' Then
  906.       bAccess    := TRUE;
  907.   {$ENDIF}
  908.   For i := 0 To FSelectFields.Count - 1 Do
  909.   Begin
  910.       if i <> 0 Then
  911.          StSQL    := StSQL + ',';
  912.      SQL.Add (StSQL);
  913.      StSQL    := '';
  914.      StSQL    := StSQL + TEXT_TAB;
  915.      FieldPtr    := FSelectFields[i];
  916.      if FieldPtr = nil Then Continue;
  917.  
  918.      {$IFDEF VERIFY_MSACCESS}
  919.      if bAccess Then
  920.          StrCatStrNotString (FieldPtr.Data)
  921.      Else
  922.      {$ENDIF}
  923.          StSQL    := StSQL + FieldPtr.Data;
  924.         if FieldPtr.ColumnName <> '' Then
  925.         Begin
  926.             StSQL    := StSQL + ' AS ';
  927.         StSQL    := StSQL + FieldPtr.ColumnName;
  928.      End;
  929.   End;
  930. //QueryLB:
  931.     if FTables.Count <= 0 Then Goto ExieSQL;
  932.   bOuter    := FALSE;
  933.   bWhere    := FALSE;
  934.  
  935.     For i := 0 To FTables.Count - 1 Do
  936.   Begin
  937.       TablePtr    := FTables[i];
  938.         if TablePtr = nil Then Continue;
  939.       if FindOuter (TRUE) Then Continue;
  940.  
  941.       if i = 0 Then
  942.      Begin
  943.          SQL.Add (StSQL);
  944.          StSQL    := '';
  945.             StSQL    := StSQL + 'FROM';
  946.      End
  947.      Else
  948.          StSQL    := StSQL + ',';
  949.      SQL.Add (StSQL);
  950.      StSQL    := '';
  951.      StSQL    := StSQL + TEXT_TAB;
  952.         PutTable (TablePtr);
  953.      bOuter            := FindOuter (FALSE);
  954.      TableOuterPtr    := nil;
  955.      if bOuter Then
  956.             TableOuterPtr    := FTables.FindAsStringPt (LinkOPtr.DAlias);
  957.      if TableOuterPtr = nil Then Continue;
  958.      { Have Outer Join }
  959.  
  960.      Case LinkOPtr.TableLinkType of
  961.          tltLeftOuter:    StSQL    := StSQL + ' LEFT OUTER JOIN ';
  962.         tltRightOuter:    StSQL    := StSQL + ' RIGHT OUTER JOIN ';
  963.      End;
  964.      PutTable (TableOuterPtr);
  965.  
  966.      SQL.Add (StSQL);
  967.      StSQL    := '';
  968.      StSQL    := StSQL + TEXT_TAB;
  969.      StSQL    := StSQL + 'ON (';
  970.      StSQL    := StSQL + LinkOPtr.MAlias;
  971.      StSQL    := StSQL + '.';
  972.      {$IFDEF VERIFY_MSACCESS}
  973.      if bAccess Then
  974.         StSQL    := StSQL + '[' + LinkOPtr.MField + ']'
  975.      Else
  976.      {$ENDIF}
  977.          StSQL    := StSQL + '''' + LinkOPtr.MField + '''';
  978.  
  979.      StSQL    := StSQL + ' = ';
  980.      StSQL    := StSQL + LinkOPtr.DAlias;
  981.         StSQL    := StSQL + '.';
  982.      {$IFDEF VERIFY_MSACCESS}
  983.      if bAccess Then
  984.         StSQL    := StSQL + '[' + LinkOPtr.DField + ']'
  985.      Else
  986.      {$ENDIF}
  987.          StSQL    := StSQL + '''' + LinkOPtr.DField + '''';
  988.      StSQL    := StSQL + ')';
  989.   End;
  990.   For i := 0 To DQTableLinks.Count - 1 Do
  991.   Begin
  992.       LinkPtr    := DQTableLinks[i];
  993.         if LinkPtr = nil Then Continue;
  994.       Case LinkPtr.TableLinkType of
  995.          tltLeftOuter,
  996.          tltRightOuter:    Continue;
  997.      End;
  998.  
  999.       if i = 0 Then
  1000.      Begin
  1001.          SQL.Add (StSQL);
  1002.          StSQL    := '';
  1003.             StSQL    := StSQL + 'WHERE';
  1004.         bWhere    := TRUE;
  1005.      End
  1006.      Else
  1007.          StSQL    := StSQL + ' AND ';
  1008.      SQL.Add (StSQL);
  1009.      StSQL    := '';
  1010.      StSQL    := StSQL + TEXT_TAB;
  1011.      LinkPtr    := DQTableLinks[i];
  1012.         if LinkPtr = nil Then Continue;
  1013.  
  1014.             StSQL    := StSQL + '(';
  1015.         StSQL    := StSQL + LinkPtr.MAlias;
  1016.         StSQL    := StSQL + '.';
  1017.         {$IFDEF VERIFY_MSACCESS}
  1018.         if bAccess Then
  1019.            StSQL    := StSQL + '[' + LinkPtr.MField + ']'
  1020.         Else
  1021.         {$ENDIF}
  1022.                 StSQL    := StSQL + '''' + LinkPtr.MField + '''';
  1023.             Case LinkPtr.TableLinkType of
  1024.                 tltEqual:            {=}        StSQL    := StSQL + ' = ';
  1025.            tltGreater:            {>}        StSQL    := StSQL + ' > ';
  1026.            tltLess:                {<}        StSQL    := StSQL + ' > ';
  1027.            tltGreaterEqual:    {>=}        StSQL    := StSQL + ' >= ';
  1028.               tltLessEqual:        {<=}        StSQL    := StSQL + ' <= ';
  1029.            tltNotEqual:        {<>}        StSQL    := StSQL + ' <> ';
  1030.         Else
  1031.             StSQL    := StSQL + ' = ';
  1032.             End;
  1033.             StSQL    := StSQL + LinkPtr.DAlias;
  1034.         StSQL    := StSQL + '.';
  1035.  
  1036.         {$IFDEF VERIFY_MSACCESS}
  1037.         if bAccess Then
  1038.            StSQL    := StSQL + '[' + LinkPtr.DField + ']'
  1039.         Else
  1040.         {$ENDIF}
  1041.                 StSQL    := StSQL + '''' + LinkPtr.DField + '''';
  1042.  
  1043.         StSQL    := StSQL + ')';
  1044.     End;
  1045.  
  1046.   For i := 0 To DQCriterias.Count - 1 Do
  1047.   Begin
  1048.       CriteriasPtr    := DQCriterias[i];
  1049.       if (i = 0) and (bWhere = FALSE) Then
  1050.      Begin
  1051.          SQL.Add (StSQL);
  1052.          StSQL    := '';
  1053.          StSQL    := StSQL + 'WHERE';
  1054.      End
  1055.      Else
  1056.      Begin
  1057.          if i = 0 Then
  1058.                 StSQL    := StSQL + ' AND'
  1059.         Else
  1060.         Begin
  1061.             if CriteriasPtr.AddType = caAnd Then
  1062.                     StSQL    := StSQL + ' AND'
  1063.            Else
  1064.                StSQL    := StSQL + ' OR';
  1065.         End;
  1066.      End;
  1067.      SQL.Add (StSQL);
  1068.      StSQL    := '';
  1069.      StSQL    := StSQL + TEXT_TAB;
  1070.      StSQL    := StSQL + '(';
  1071.      StSQL    := StSQL + CriteriasPtr.Field;
  1072.      Case CriteriasPtr.CriteriaType of
  1073.          scEqual:                StSQL    := StSQL + ' = ';
  1074.         scNotEqual:            StSQL    := StSQL + ' <> ';
  1075.          scLess:                StSQL    := StSQL + ' < ';
  1076.          scLessEqual:        StSQL    := StSQL + ' <= ';
  1077.          scGreater:            StSQL    := StSQL + ' > ';
  1078.             scGreaterEqual:    StSQL    := StSQL + ' >= ';
  1079.          scBetween:            StSQL    := StSQL + ' > ';
  1080.          scBetweenEqual:    StSQL    := StSQL + ' >= ';
  1081.         scNULL:
  1082.             Begin
  1083.                StSQL    := StSQL + ' IS NULL)';
  1084.               Continue;
  1085.            End;
  1086.         scNOTNULL:
  1087.             Begin
  1088.                StSQL    := StSQL + ' IS NOT NULL)';
  1089.               Continue;
  1090.            End;
  1091.         scIN:                StSQL    := StSQL + ' IN ( ';
  1092.         scLike:            StSQL    := StSQL + ' LIKE ';
  1093.         scNotLike:        StSQL    := StSQL + ' NOT LIKE ';
  1094.      End;
  1095.      StSQL    := StSQL + CriteriasPtr.Value1;
  1096.      StSQL    := StSQL + ')';
  1097.      Case CriteriasPtr.CriteriaType of
  1098.             scEqual,
  1099.         scNotEqual,
  1100.          scLess,
  1101.          scLessEqual,
  1102.          scGreater,
  1103.             scGreaterEqual,
  1104.         scNOTNULL,
  1105.         scLike,
  1106.         scNotLike:        Continue;
  1107.             scIN:
  1108.             Begin
  1109.                StSQL    := StSQL + ')';
  1110.               Continue;
  1111.            End;
  1112.         End;
  1113.      StSQL    := StSQL + ' And (';
  1114.      StSQL    := StSQL + CriteriasPtr.Field;
  1115.      Case CriteriasPtr.CriteriaType of
  1116.          scBetween:            StSQL    := StSQL + ' < ';
  1117.          scBetweenEqual:    StSQL    := StSQL + ' <= ';
  1118.         End;
  1119.         StSQL    := StSQL + CriteriasPtr.Value2;
  1120.      StSQL    := StSQL + ')';
  1121.   End;
  1122.  
  1123.   For i := 0 To FGroups.Count - 1 Do
  1124.   Begin
  1125.       GroupPtr    := FGroups[i];
  1126.      if GroupPtr = nil Then Continue;
  1127.       if i = 0 Then
  1128.      Begin
  1129.          SQL.Add (StSQL);
  1130.          StSQL    := '';
  1131.             StSQL    := StSQL + 'GROUP BY';
  1132.      End
  1133.      Else
  1134.          StSQL    := StSQL + ',';
  1135.      SQL.Add (StSQL);
  1136.      StSQL    := '';
  1137.      StSQL    := StSQL + TEXT_TAB;
  1138.  
  1139.      {$IFDEF VERIFY_MSACCESS}
  1140.      if bAccess Then
  1141.      Begin
  1142.          iTemp        := FSelectFields.FindAsString (GroupPtr.Field);
  1143.         if iTemp >= 0 Then
  1144.         Begin
  1145.              FieldPtr    := FSelectFields[iTemp];
  1146.             if FieldPtr = nil Then
  1147.                 StSQL    := StSQL + GroupPtr.Field
  1148.             Else
  1149.                 StrCatStrNotString (FieldPtr.Data);
  1150.         End
  1151.         Else
  1152.             StSQL    := StSQL + GroupPtr.Field;
  1153.      End
  1154.      Else
  1155.      {$ENDIF}
  1156.          StSQL    := StSQL + GroupPtr.Field;
  1157.   End;
  1158.   For i := 0 To FSorts.Count - 1 Do
  1159.   Begin
  1160.       SortPtr    := FSorts[i];
  1161.      if SortPtr = nil Then Continue;
  1162.       if i = 0 Then
  1163.      Begin
  1164.          SQL.Add (StSQL);
  1165.          StSQL    := '';
  1166.             StSQL    := StSQL + 'ORDER BY';
  1167.      End
  1168.      Else
  1169.          StSQL    := StSQL + ',';
  1170.      SQL.Add (StSQL);
  1171.      StSQL    := '';
  1172.      StSQL    := StSQL + TEXT_TAB;
  1173.      {$IFDEF VERIFY_MSACCESS}
  1174.      if bAccess Then
  1175.      Begin
  1176.          iTemp        := FSelectFields.FindAsString (SortPtr.Field);
  1177.         if iTemp >= 0 Then
  1178.         Begin
  1179.              FieldPtr    := FSelectFields[iTemp];
  1180.             if FieldPtr = nil Then
  1181.                 StSQL    := StSQL + SortPtr.Field
  1182.             Else
  1183.                 StrCatStrNotString (FieldPtr.Data);
  1184.         End
  1185.         Else
  1186.             StSQL    := StSQL + SortPtr.Field;
  1187.      End
  1188.      Else
  1189.      {$ENDIF}
  1190.          StSQL    := StSQL + SortPtr.Field;
  1191.         Case SortPtr.SortType of
  1192.          gsAscending:    StSQL    := StSQL + ' ASC';
  1193.         gsDecending:    StSQL    := StSQL + ' DESC';
  1194.      End;
  1195.   End;
  1196.   if StSQL <> '' Then
  1197.       SQL.Add (StSQL);
  1198. ExieSQL:
  1199.   Finally
  1200.       SQL.EndUpdate;
  1201.      {$IFDEF VERIFY_MSACCESS}
  1202.       if bAccess Then
  1203.          Self.DatabaseName    := StDB;
  1204.       {$ENDIF}
  1205.   End;
  1206. End;
  1207. Function TDuckQuery.SaveFile (StFile: String): Boolean;
  1208. Var
  1209.   Stream:    THandleStream;
  1210.   iFile:    Integer;
  1211. Begin
  1212.     Result    := FALSE;
  1213.     iFile        := FileCreate (StFile);
  1214.     if iFile <= 0 Then
  1215.       raise Exception.CreateFmt ('Can''t save file %s', [StFile]);
  1216.     Stream        := THandleStream.Create (iFile);
  1217.     Try
  1218.         SaveToStream(Stream);
  1219.   Finally
  1220.         Stream.Free;
  1221.      FileClose (iFile);
  1222.     End;
  1223.   Result    := TRUE;
  1224. End;
  1225. Procedure TDuckQuery.SaveToStream (Stream: TStream);
  1226. Var
  1227.     i:                    Integer;
  1228.   TablePtr:        PRDQTable;
  1229.     LinkPtr:            PRDQLink;
  1230.   FieldPtr:        PRDQField;
  1231.   CriteriasPtr:    PRDQCriterias;
  1232.   GroupPtr:        PRDQGroup;
  1233.   SortPtr:            PRDQSort;
  1234.     Procedure    WriteString (St: String);
  1235.     Var
  1236.         wSize:    Word;
  1237.     Begin
  1238.         wSize    := Length (St);
  1239.       Stream.WriteBuffer (wSize, Sizeof (Word));
  1240.       if wSize > 0 Then
  1241.           Stream.WriteBuffer (St[1], wSize);
  1242.   End;
  1243.   Procedure    WriteCount (iCount: Integer);
  1244.   Begin
  1245.       Stream.WriteBuffer (iCount, Sizeof (iCount));
  1246.   End;
  1247. Begin
  1248.     Stream.WriteBuffer (DQ_PTHIS_VERSION, 4);
  1249.   Stream.WriteBuffer (FDuplicate, Sizeof (FDuplicate));
  1250.  
  1251.   WriteCount (FTables.Count);
  1252.     For i := 0 To FTables.Count - 1 Do
  1253.     Begin
  1254.       TablePtr    := FTables[i];
  1255.      WriteString (TablePtr.DataBase);
  1256.      WriteString (TablePtr.Table);
  1257.      WriteString (TablePtr.Alias);
  1258.     End;
  1259.  
  1260.   WriteCount (FTableLink.Count);
  1261.   For i := 0 To FTableLink.Count - 1 Do
  1262.     Begin
  1263.       LinkPtr    := FTableLink[i];
  1264.      Stream.WriteBuffer (LinkPtr.TableLinkType, Sizeof (TDQLinkType));
  1265.         WriteString (LinkPtr.MAlias);
  1266.         WriteString (LinkPtr.MField);
  1267.         WriteString (LinkPtr.DAlias);
  1268.      WriteString (LinkPtr.DField);
  1269.     End;
  1270.  
  1271.   WriteCount (FSelectFields.Count);
  1272.   For i := 0 To FSelectFields.Count - 1 Do
  1273.     Begin
  1274.       FieldPtr    := FSelectFields[i];
  1275.         WriteString (FieldPtr.Data);
  1276.         WriteString (FieldPtr.ColumnName);
  1277.     End;
  1278.  
  1279.   WriteCount (FCriterias.Count);
  1280.   For i := 0 To FCriterias.Count - 1 Do
  1281.     Begin
  1282.       CriteriasPtr    := FCriterias[i];
  1283.         WriteString (CriteriasPtr.Field);
  1284.      Stream.WriteBuffer (CriteriasPtr.CriteriaType, Sizeof (TDQCriteriaType));
  1285.      WriteString (CriteriasPtr.Value1);
  1286.      WriteString (CriteriasPtr.Value2);
  1287.      Stream.WriteBuffer (CriteriasPtr.AddType, Sizeof (TDQCriteriaAdd));
  1288.     End;
  1289.  
  1290.   WriteCount (FGroups.Count);
  1291.   For i := 0 To FGroups.Count - 1 Do
  1292.     Begin
  1293.       GroupPtr    := FGroups[i];
  1294.         WriteString (GroupPtr.Field);
  1295.     End;
  1296.  
  1297.   WriteCount (FSorts.Count);
  1298.   For i := 0 To FSorts.Count - 1 Do
  1299.     Begin
  1300.       SortPtr    := FSorts[i];
  1301.      Stream.WriteBuffer (SortPtr.SortType, Sizeof (TDQSortType));
  1302.         WriteString (SortPtr.Field);
  1303.     End;
  1304. End;
  1305. Function TDuckQuery.OpenFile (StFile: String): Boolean;
  1306. Var
  1307.   iFile:    Integer;
  1308.     Stream:    THandleStream;
  1309. Begin
  1310.   iFile    := FileOpen (StFile, fmOpenRead or fmShareDenyNone);
  1311.     if iFile <= 0 Then
  1312.       raise Exception.CreateFmt ('Can''t open file %s.', [StFile]);
  1313.   Clear;
  1314.   Stream        := THandleStream.Create (iFile);
  1315.   Try
  1316.       Result    := LoadFromStream (Stream);
  1317.   Finally
  1318.         Stream.Free;
  1319.      FileClose (iFile);
  1320.      if Result Then
  1321.          DoSQL;
  1322.     End;
  1323. End;
  1324. Function TDuckQuery.LoadFromStream (Stream: TStream): Boolean;
  1325. Var
  1326.     StVersion:    String;
  1327.   iThis:        Integer;
  1328.   i:                Integer;
  1329.   St:            String;
  1330.   StFile:        TFileName;
  1331.  
  1332.   TablePtr:        RDQTable;
  1333.     LinkPtr:            RDQLink;
  1334.   FieldPtr:        RDQField;
  1335.   CriteriasPtr:    RDQCriterias;
  1336.   GroupPtr:        RDQGroup;
  1337.   SortPtr:            RDQSort;
  1338.   iCount:            Integer;
  1339.  
  1340.   Function    ReadString: String;
  1341.     Var
  1342.         wSize:    Word;
  1343.       lpCh:        PChar;
  1344.     Begin
  1345.         Stream.ReadBuffer (wSize, Sizeof (Word));
  1346.       SetLength (Result, wSize);
  1347.       if wSize > 0 Then
  1348.           Stream.ReadBuffer (Result[1], wSize);
  1349.     End;
  1350.   Function    ReadCount: Integer;
  1351.   Begin
  1352.       Result    := 0;
  1353.      Stream.ReadBuffer (Result, Sizeof (Integer));
  1354.   End;
  1355. Begin
  1356.     Result    := FALSE;
  1357.   SetLength (StVersion, 4);
  1358.     Stream.ReadBuffer (StVersion[1], 4);
  1359.     FVersion        := DQGetVersion (StVersion);
  1360.   if FVersion = 0 Then
  1361.       raise Exception.Create ('This is not a valid Duck Query file.');
  1362.     iThis            := DQGetVersion (DQ_PTHIS_VERSION);
  1363.     if FVersion > iThis Then
  1364.      raise Exception.Create ('Incorrect Version');
  1365.  
  1366.   Stream.ReadBuffer (FDuplicate, Sizeof (FDuplicate));
  1367.  
  1368.   iCount    := ReadCount;
  1369.     For i := 0 To iCount - 1 Do
  1370.     Begin
  1371.      TablePtr.DataBase    := ReadString;
  1372.      TablePtr.Table        := ReadString;
  1373.      TablePtr.Alias        := ReadString;
  1374.      FTables.Add (@TablePtr);
  1375.     End;
  1376.  
  1377.   iCount    := ReadCount;
  1378.     For i := 0 To iCount - 1 Do
  1379.     Begin
  1380.      Stream.ReadBuffer (LinkPtr.TableLinkType, Sizeof (TDQLinkType));
  1381.         LinkPtr.MAlias        := ReadString;
  1382.         LinkPtr.MField        := ReadString;
  1383.         LinkPtr.DAlias        := ReadString;
  1384.      LinkPtr.DField        := ReadString;
  1385.      FTableLink.Add (@LinkPtr);
  1386.     End;
  1387.  
  1388.     iCount    := ReadCount;
  1389.     For i := 0 To iCount - 1 Do
  1390.     Begin
  1391.         FieldPtr.Data            := ReadString;
  1392.         FieldPtr.ColumnName    := ReadString;
  1393.      FSelectFields.Add (@FieldPtr);
  1394.     End;
  1395.  
  1396.   iCount    := ReadCount;
  1397.     For i := 0 To iCount - 1 Do
  1398.     Begin
  1399.         CriteriasPtr.Field    := ReadString;
  1400.      Stream.ReadBuffer (CriteriasPtr.CriteriaType, Sizeof (TDQCriteriaType));
  1401.      CriteriasPtr.Value1    := ReadString;
  1402.      CriteriasPtr.Value2    := ReadString;
  1403.      Stream.ReadBuffer (CriteriasPtr.AddType, Sizeof (TDQCriteriaAdd));
  1404.      FCriterias.Add (@CriteriasPtr);
  1405.     End;
  1406.  
  1407.   iCount    := ReadCount;
  1408.     For i := 0 To iCount - 1 Do
  1409.     Begin
  1410.         GroupPtr.Field    := ReadString;
  1411.      FGroups.Add (@GroupPtr);
  1412.     End;
  1413.  
  1414.   iCount    := ReadCount;
  1415.     For i := 0 To iCount - 1 Do
  1416.     Begin
  1417.      Stream.ReadBuffer (SortPtr.SortType, Sizeof (TDQSortType));
  1418.         SortPtr.Field    := ReadString;
  1419.      FSorts.Add (@SortPtr);
  1420.     End;
  1421.   Result    := TRUE;
  1422. End;
  1423. Function TDuckQuery.SaveTextFile (StFile: String): Boolean;
  1424. Var
  1425.   Items:    TStrings;
  1426. Begin
  1427.     Result    := FALSE;
  1428.   Items        := TStrings.Create;
  1429.     Try
  1430.       GetSQL (Items);
  1431.      Items.SaveToFile (StFile);
  1432.   Finally
  1433.       Items.Free;
  1434.     End;
  1435.   Result    := TRUE;
  1436. End;
  1437. Procedure TDuckQuery.Editor (Index: Integer);
  1438. Begin
  1439.     FormQuery        := TFormQuery.Create (nil);
  1440.   FormQuery.TNotebook.PageIndex    := Index;
  1441.   FormQuery.DuckQuery.Assign (Self);
  1442.   FormQuery.ShowModal;
  1443.   Try
  1444.       if FormQuery.ModalResult = mrOK Then
  1445.       Begin
  1446.         Self.Assign (FormQuery.DuckQuery);
  1447.         if Active Then
  1448.             Active    := FALSE;
  1449.             DoSQL;
  1450.      End;
  1451.   Finally
  1452.       FormQuery.Free;
  1453.   End;
  1454. End;
  1455. Function TDuckQuery.OpenFileDlg: Boolean;
  1456. Var
  1457.     OpenDlg:        TOpenDialog;
  1458. Begin
  1459.     Result    := FALSE;
  1460.     OpenDlg                    := TOpenDialog.Create (nil);
  1461.     OpenDlg.DefaultExt    := 'dqf';
  1462.     OpenDlg.Filter            := 'Duck Query (*.dqf)|*.dqf|All File (*.*)|*.*';
  1463.     OpenDlg.FileName        := '';
  1464.   if not OpenDlg.Execute Then
  1465.     Begin
  1466.         OpenDlg.Free;
  1467.      Exit;
  1468.   End;
  1469.   Try
  1470.       Result    := OpenFile (OpenDlg.FileName);
  1471.   Finally
  1472.       OpenDlg.Free;
  1473.   End;
  1474. End;
  1475. Function TDuckQuery.SaveFileDlg: Boolean;
  1476. Var
  1477.     SaveDlg:        TSaveDialog;
  1478. Begin
  1479.     Result    := FALSE;
  1480.     SaveDlg    := TSaveDialog.Create (nil);
  1481.     SaveDlg.DefaultExt    := 'dqf';
  1482.     SaveDlg.Filter            := 'Duck Query (*.dqf)|*.dqf|All File (*.*)|*.*';
  1483.     SaveDlg.FileName        := '';
  1484.     if not SaveDlg.Execute Then
  1485.   Begin
  1486.         SaveDlg.Free;
  1487.      Exit;
  1488.   End;
  1489.   Try
  1490.         Result    := SaveFile (SaveDlg.FileName);
  1491.   Finally
  1492.       SaveDlg.Free;
  1493.     End;
  1494. End;
  1495. Function TDuckQuery.SaveTxtFileDlg: Boolean;
  1496. Var
  1497.     SaveDlg:        TSaveDialog;
  1498. Begin
  1499.     Result    := FALSE;
  1500.     SaveDlg    := TSaveDialog.Create (nil);
  1501.     SaveDlg.DefaultExt    := 'txt';
  1502.   SaveDlg.Filter            := 'Text Document (*.txt)|*.txt|All File (*.*)|*.*';
  1503.     SaveDlg.FileName        := '';
  1504.     if not SaveDlg.Execute Then
  1505.   Begin
  1506.         SaveDlg.Free;
  1507.      Exit;
  1508.   End;
  1509.   Try
  1510.         Result    := SaveTextFile (SaveDlg.FileName);
  1511.   Finally
  1512.       SaveDlg.Free;
  1513.     End;
  1514. End;
  1515. Procedure TDuckQuery.ViewSQL;
  1516. Begin
  1517.     FormDQViewText    := TFormDQViewText.Create (nil);
  1518.     GetSQL (FormDQViewText.Memo.Lines);
  1519.     FormDQViewText.ShowModal;
  1520.     FormDQViewText.Free;
  1521. End;
  1522. End.
  1523.